package com.jsu.clubmanagementsystem.service.application.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jsu.clubmanagementsystem.common.ErrorCode;
import com.jsu.clubmanagementsystem.common.PageQueryRequest;
import com.jsu.clubmanagementsystem.constant.UserConstant;
import com.jsu.clubmanagementsystem.exception.BusinessException;
import com.jsu.clubmanagementsystem.model.dto.activityapplication.ActivityApplicationAddRequest;
import com.jsu.clubmanagementsystem.model.dto.activityapplication.ActivityApplicationAdditionalInfo;
import com.jsu.clubmanagementsystem.model.dto.activityapplication.ActivityApplicationQueryRequest;
import com.jsu.clubmanagementsystem.model.entity.*;
import com.jsu.clubmanagementsystem.model.enums.ActivityStatusEnum;
import com.jsu.clubmanagementsystem.model.enums.ApplicationTypeEnum;
import com.jsu.clubmanagementsystem.model.enums.ReviewResultEnum;
import com.jsu.clubmanagementsystem.model.vo.activityApplication.ActivityApplicationVO;
import com.jsu.clubmanagementsystem.model.vo.activity.ActivityVO;
import com.jsu.clubmanagementsystem.model.vo.club.ClubVO;
import com.jsu.clubmanagementsystem.model.vo.user.UserVO;
import com.jsu.clubmanagementsystem.mapper.ActivityApplicationMapper;
import com.jsu.clubmanagementsystem.model.vo.review.ReviewVO;
import com.jsu.clubmanagementsystem.service.activity.ActivityService;
import com.jsu.clubmanagementsystem.service.application.ActivityApplicationService;
import com.jsu.clubmanagementsystem.service.application.UserApplicationService;
import com.jsu.clubmanagementsystem.service.club.ClubService;
import com.jsu.clubmanagementsystem.service.review.ReviewService;
import com.jsu.clubmanagementsystem.service.user.UserService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 24753
* @description 针对表【activity_application(社团活动相关申请)】的数据库操作Service实现
* @createDate 2025-05-17 17:05:46
*/
@Service
public class ActivityApplicationServiceImpl extends ServiceImpl<ActivityApplicationMapper, ActivityApplication>
        implements ActivityApplicationService {

    @Resource
    private UserService userService;

    @Resource
    private ClubService clubService;

    @Resource
    private ActivityService activityService;

    @Resource
    @Lazy
    private UserApplicationService userApplicationService;

    @Resource
    @Lazy
    private ReviewService reviewService;

    /**
     * 处理活动申请
     *
     * @param addRequest 申请请求
     * @return 申请ID
     */
    @Override
    public Long processActivityApplication(ActivityApplicationAddRequest addRequest) {
        ActivityApplication activityApplication = new ActivityApplication();
        BeanUtils.copyProperties(addRequest, activityApplication);
        activityApplication.setAdditionalInfo(JSONUtil.toJsonStr(addRequest.getAdditionalInfo()));
        activityApplication.setResult(ReviewResultEnum.WAITING.getCode());
        activityApplicationValidation(activityApplication);

        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(activityApplication.getType());
        switch (applicationType) {
            case CREATE_ACTIVITY:
                return addCreateActivityApplication(activityApplication);
            case DELETE_ACTIVITY:
                return addDeleteActivityApplication(activityApplication);
            case CHANGE_ACTIVITY_INFO:
                return addUpdateActivityApplication(activityApplication);
            default:
                throw new BusinessException(ErrorCode.PARAM_ERROR, "无效的活动申请类型");
        }
    }

    /**
     * 提交举办活动申请
     *
     * @param activityApplication 申请
     * @return 申请ID
     */
    public Long addCreateActivityApplication(ActivityApplication activityApplication) {
        Long userId = activityApplication.getUserId();
        Long clubId = activityApplication.getTargetId();  // 社团ID
        if (!clubService.isManagerOfClub(userId, clubId)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "只有本社团社长才能申请举办活动");
        }
        if (this.isExist(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!this.save(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return activityApplication.getId();
    }

    /**
     * 提交取消活动申请
     * @param activityApplication 申请
     * @return 申请ID
     */
    public Long addDeleteActivityApplication(ActivityApplication activityApplication) {
        Long userId = activityApplication.getUserId();
        Long activityId = activityApplication.getTargetId();
        Activity activity = activityService.getById(activityId);
        if (activity == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "活动不存在");
        }
        if (!activity.getStatus().equals(ActivityStatusEnum.READY.getCode())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "只能取消已确定举办的活动");
        }
        if (!clubService.isManagerOfClub(userId, activity.getClubId())) {
            throw new BusinessException(ErrorCode.NO_AUTH, "只有社长才能申请取消活动");
        }

        activityApplication.setAdditionalInfo("{}");
        activityApplication.setStartTime(activity.getStartTime());
        activityApplication.setEndTime(activity.getEndTime());

        // 活动是否还有未被审核的申请
        QueryWrapper<UserApplication> userApplicationQueryWrapper = new QueryWrapper<>();
        userApplicationQueryWrapper.in("type",
                ApplicationTypeEnum.ENGAGE_ACTIVITY.getCode(), ApplicationTypeEnum.QUIT_ACTIVITY.getCode());
        userApplicationQueryWrapper.eq("additionalInfo", activityId);
        userApplicationQueryWrapper.eq("result", ReviewResultEnum.WAITING.getCode());
        if (userApplicationService.count(userApplicationQueryWrapper) > 0){
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "活动还有未审核的申请");
        }

        if (this.isExist(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!this.save(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return activityApplication.getId();
    }

    /**
     * 提交修改活动信息申请
     *
     * @param activityApplication 申请
     * @return 申请ID
     */
    public Long addUpdateActivityApplication(ActivityApplication activityApplication) {
        Long userId = activityApplication.getUserId();
        Long activityId = activityApplication.getTargetId();  // 活动ID
        Activity activity = activityService.getById(activityId);
        if (activity == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "活动不存在");
        }
        if (!activity.getStatus().equals(ActivityStatusEnum.READY.getCode())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "只能修改已确定举办的活动");
        }
        if (!clubService.isManagerOfClub(userId, activity.getClubId())) {
            throw new BusinessException(ErrorCode.NO_AUTH, "只有社长才能申请修改活动信息");
        }

        if (this.isExist(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "用户已提交过申请");
        }
        if (!this.save(activityApplication)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "提交申请失败");
        }
        return activityApplication.getId();
    }

    /**
     * 获得封装对象
     *
     * @param activityApplication 活动申请实体
     * @return 活动申请VO
     */
    @Override
    public ActivityApplicationVO getActivityApplicationVO(ActivityApplication activityApplication) {
        if (activityApplication == null) {
            return null;
        }
        // 设置基本信息和附加值封装
        ActivityApplicationVO activityApplicationVO = new ActivityApplicationVO();
        BeanUtils.copyProperties(activityApplication, activityApplicationVO);
        ActivityApplicationAdditionalInfo additionalInfo = JSONUtil.toBean(activityApplication.getAdditionalInfo(), ActivityApplicationAdditionalInfo.class);
        activityApplicationVO.setAdditionalInfo(additionalInfo);

        // 设置审核结果封装
        if (!activityApplication.getResult().equals(ReviewResultEnum.WAITING.getCode())) {
            Long applicationId = activityApplication.getId();
            Integer applicationType = activityApplication.getType();
            activityApplicationVO.setReviewVO(reviewService.getReviewVoByApplication(applicationId, applicationType));
        } else {
            ReviewVO reviewVO = new ReviewVO();
            reviewVO.setResult(ReviewResultEnum.WAITING.getInfo());
            activityApplicationVO.setReviewVO(reviewVO);
        }

        // 设置申请用户信息
        Long userId = activityApplication.getUserId();
        User user = userService.getById(userId);
        if (user != null) {
            UserVO userVO = UserVO.objToVoAllInfo(user);
            activityApplicationVO.setUserVO(userVO);
        }

        // 设置目标活动信息和社团信息
        Long clubId = null;
        Integer type = activityApplication.getType();
        if (type.equals(ApplicationTypeEnum.CREATE_ACTIVITY.getCode())) {
            clubId = activityApplication.getTargetId();
        } else {
            Long activityId = activityApplication.getTargetId();
            Activity activity = activityService.getById(activityId);

            if (activity != null) {
                ActivityVO activityVO = ActivityVO.objToVo(activity);
                activityApplicationVO.setActivityVO(activityVO);
                clubId = activity.getClubId();
            }
        }

        Club club = clubService.getById(clubId);
        if (club != null) {
            ClubVO clubVO = ClubVO.objToVo(club);
            activityApplicationVO.setClubVO(clubVO);
        }
        return activityApplicationVO;
    }

    /**
     * 查询活动申请列表
     *
     * @param activityApplicationQueryRequest 查询请求
     * @return 分页结果
     */
    @Override
    public Page<ActivityApplicationVO> listActivityApplicationVOByPage(ActivityApplicationQueryRequest activityApplicationQueryRequest,
                                                                       User user) {
        if (activityApplicationQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }

        Integer type = activityApplicationQueryRequest.getType();
        Long targetId = activityApplicationQueryRequest.getTargetId();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType != null &&
                !applicationType.equals(ApplicationTypeEnum.CREATE_ACTIVITY) &&
                !applicationType.equals(ApplicationTypeEnum.DELETE_ACTIVITY) &&
                !applicationType.equals(ApplicationTypeEnum.CHANGE_ACTIVITY_INFO)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "未知的申请类型");
        }
        if (targetId != null && applicationType == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少申请类型参数");
        }

        Integer result = activityApplicationQueryRequest.getResult();
        if (result != null) {
            ReviewResultEnum reviewResult = ReviewResultEnum.getByCode(result);
            if (reviewResult == null) {
                throw new BusinessException(ErrorCode.PARAM_ERROR, "未知的审核状态");
            }
        }

        QueryWrapper<ActivityApplication> queryWrapper = null;
        List<ActivityApplication> applicationList = new ArrayList<>();
        if (user.getUserRole().equals(UserConstant.USER_ROLE_MANAGER)) {
            Long clubId = user.getManagedClubId();
            List<Activity> activityListOfClub = activityService.getActivityListOfClub(clubId);
            List<Long> activityIdListOfClub = activityListOfClub.stream().map(Activity::getId).toList();
            Long id = activityApplicationQueryRequest.getId();

            if (applicationType == null || applicationType.equals(ApplicationTypeEnum.CREATE_ACTIVITY)) {
                queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("type", ApplicationTypeEnum.CREATE_ACTIVITY.getCode());
                queryWrapper.eq("targetId", clubId);
                queryWrapper.eq(ObjectUtils.isNotEmpty(id) && id > 0, "id", id);
                queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
                applicationList.addAll(this.list(queryWrapper));
            }
            if (!activityListOfClub.isEmpty() &&
                    (applicationType == null || applicationType.equals(ApplicationTypeEnum.DELETE_ACTIVITY))) {
                queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("type", ApplicationTypeEnum.DELETE_ACTIVITY.getCode());
                queryWrapper.in("targetId", activityIdListOfClub);
                queryWrapper.eq(ObjectUtils.isNotEmpty(id) && id > 0, "id", id);
                queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
                applicationList.addAll(this.list(queryWrapper));
            }
            if (!activityListOfClub.isEmpty() &&
                    (applicationType == null || applicationType.equals(ApplicationTypeEnum.CHANGE_ACTIVITY_INFO))) {
                queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("type", ApplicationTypeEnum.CHANGE_ACTIVITY_INFO.getCode());
                queryWrapper.in("targetId", activityIdListOfClub);
                queryWrapper.eq(ObjectUtils.isNotEmpty(id) && id > 0, "id", id);
                queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
                applicationList.addAll(this.list(queryWrapper));
            }
        } else {
            queryWrapper = this.getQueryWrapper(activityApplicationQueryRequest);
            applicationList.addAll(this.list(queryWrapper));
        }
        List<ActivityApplicationVO> activityApplicationVOList = applicationList.stream()
                .map(this::getActivityApplicationVO)
                .collect(Collectors.toList());

        long current = activityApplicationQueryRequest.getCurrent();
        long size = activityApplicationQueryRequest.getPageSize();
        Page<ActivityApplicationVO> activityApplicationVOPage = new Page<>(current, size);
        activityApplicationVOPage.setRecords(activityApplicationVOList);
        return activityApplicationVOPage;
    }

    /**
     * 申请是否存在
     *
     * @param applicationId
     * @return
     */
    public boolean isExist(Long applicationId) {
        if (applicationId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        return this.getById(applicationId) != null;
    }

    /**
     * 申请是否存在
     * @param applicationId
     * @param type
     * @return
     */
    public boolean isExist(Long applicationId, Integer type) {
        if (applicationId == null || type == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "缺少参数");
        }
        ActivityApplication application = this.getById(applicationId);
        if (application != null) {
            return application.getType().equals(type);
        }
        return false;
    }

    /**
     * 申请是否已存在
     *
     * @param activityApplication
     * @return
     */
    @Override
    public boolean isExist(ActivityApplication activityApplication) {
        if (activityApplication == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }
        Long userId = activityApplication.getUserId();
        Long targetId = activityApplication.getTargetId();
        Integer type = activityApplication.getType();
        if (userId == null || targetId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "用户ID或目标ID为空");
        }

        QueryWrapper<ActivityApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("result", ReviewResultEnum.WAITING.getCode()); // 只查待审核的申请
        queryWrapper.eq("type", type);
        queryWrapper.eq("userId", userId);
        queryWrapper.eq("targetId", targetId);
        return this.count(queryWrapper) > 0;
    }

    /**
     * 参数校验
     *
     * @param activityApplication
     */
    @Override
    public void activityApplicationValidation(ActivityApplication activityApplication) {
        if (activityApplication == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "参数为空");
        }

        Integer type = activityApplication.getType();
        ApplicationTypeEnum applicationType = ApplicationTypeEnum.getByCode(type);
        if (applicationType == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND, "未知的申请类型");
        } else if (!applicationType.equals(ApplicationTypeEnum.CREATE_ACTIVITY) &&
                !applicationType.equals(ApplicationTypeEnum.DELETE_ACTIVITY) &&
                !applicationType.equals(ApplicationTypeEnum.CHANGE_ACTIVITY_INFO)) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "不支持的活动申请类型");
        }

        Long userId = activityApplication.getUserId();
        Long targetId = activityApplication.getTargetId();
        if (userId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "申请用户为空");
        }
        if (targetId == null) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "目标社团或活动为空");
        }
        String reason = activityApplication.getReason();
        if (StringUtils.isNotBlank(reason) && reason.length() > 2048) {
            throw new BusinessException(ErrorCode.PARAM_ERROR, "申请原因过长");
        }

        // 根据申请类型进行特定校验
        if (applicationType.equals(ApplicationTypeEnum.DELETE_ACTIVITY) || applicationType.equals(ApplicationTypeEnum.CHANGE_ACTIVITY_INFO)) {
            if (!activityService.isExist(targetId)) {
                throw new BusinessException(ErrorCode.NOT_FOUND, "活动不存在");
            }
        }
        //如果是取消活动的申请，至此可以结束了
        if (applicationType.equals(ApplicationTypeEnum.DELETE_ACTIVITY)) {
            return;
        }

        String additionalInfo = activityApplication.getAdditionalInfo();
        ActivityApplicationAdditionalInfo info = JSONUtil.toBean(additionalInfo, ActivityApplicationAdditionalInfo.class);
        if (applicationType.equals(ApplicationTypeEnum.CREATE_ACTIVITY)) {
            if (StringUtils.isBlank(additionalInfo)) {
                throw new BusinessException(ErrorCode.PARAM_ERROR, "活动信息为空");
            }
            if (!clubService.isExist(targetId)){
                throw new BusinessException(ErrorCode.NOT_FOUND, "活动所属社团不存在");
            }

            // 校验活动参数
            Activity activity = new Activity();
            activity.setClubId(targetId);
            activity.setActivityName(info.getActivityName());
            activity.setActivityTitle(info.getActivityTitle());
            activity.setActivityContent(info.getActivityContent());
            activity.setStartTime(activityApplication.getStartTime());
            activity.setEndTime(activityApplication.getEndTime());
            activity.setStatus(ActivityStatusEnum.WAITING_REVIEW.getCode());
            activityService.activityValidation(activity, true);
        } else {
            // 创建修改后的活动对象，更新所修改的字段
            Activity originalActivity = activityService.getById(targetId);
            Activity updatedActivity = new Activity();
            updatedActivity.setId(targetId);
            updatedActivity.setStatus(originalActivity.getStatus());
            if (StringUtils.isNotBlank(info.getActivityName())) {
                updatedActivity.setActivityName(info.getActivityName());
            }
            if (StringUtils.isNotBlank(info.getActivityTitle())) {
                updatedActivity.setActivityTitle(info.getActivityTitle());
            }
            if (StringUtils.isNotBlank(info.getActivityContent())) {
                updatedActivity.setActivityContent(info.getActivityContent());
            }
            if (ObjectUtils.isNotEmpty(activityApplication.getStartTime())) {
                updatedActivity.setStartTime(activityApplication.getStartTime());
            }
            if (ObjectUtils.isNotEmpty(activityApplication.getEndTime())) {
                updatedActivity.setEndTime(activityApplication.getEndTime());
            }
            // 校验修改后的活动信息
            activityService.activityValidation(updatedActivity, false);
        }
    }

    /**
     * 获取查询封装
     *
     * @param activityApplicationQueryRequest 查询请求
     * @return
     */
    @Override
    public QueryWrapper<ActivityApplication> getQueryWrapper(ActivityApplicationQueryRequest activityApplicationQueryRequest) {
        QueryWrapper<ActivityApplication> queryWrapper = new QueryWrapper<>();
        if (activityApplicationQueryRequest == null) {
            return queryWrapper;
        }

        Long id = activityApplicationQueryRequest.getId();
        Long userId = activityApplicationQueryRequest.getUserId();
        Integer type = activityApplicationQueryRequest.getType();
        Integer result = activityApplicationQueryRequest.getResult();
        Long targetId = activityApplicationQueryRequest.getTargetId();

        // 添加查询条件
        queryWrapper.eq(ObjectUtils.isNotEmpty(id) && id > 0, "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId) && userId > 0, "userId", userId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(type), "type", type);
        queryWrapper.eq(ObjectUtils.isNotEmpty(result), "result", result);
        queryWrapper.eq(ObjectUtils.isNotEmpty(targetId) && targetId > 0, "targetId", targetId);
        queryWrapper.orderByDesc("createTime");  // 默认按创建时间降序排序
        return queryWrapper;
    }

    @Override
    public Page<ActivityApplication> getActivityApplicationVoPage(PageQueryRequest page) {
        String query = page.getQuery();
        Page<ActivityApplication> iPage=new Page<ActivityApplication>().setCurrent(page.getCurrent()).setSize(page.getPageSize());
        LambdaQueryWrapper<ActivityApplication> queryWrapper=new LambdaQueryWrapper<>();
        if(query!=null){
            queryWrapper.like(ActivityApplication::getId,query);
        }
        List<ActivityApplication> list = this.baseMapper.getActivityApplication(iPage, queryWrapper);
        iPage.setRecords(list).setTotal(iPage.getTotal());
        return iPage;
    }

    @Transactional
    @Override
    public boolean deleteByIds(List<Long> ids) {
        ids.forEach(id->{
            if(!this.removeById(id)){
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除操作失败");
            }
        });
        return true;
    }
}




